﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using LeksickiAnalizator;
using System.Windows.Forms;
using magic8ballUtility.Sintaksa;

namespace SintaksniAnalizator
{
    public class Program
    {
        static void Main(string[] args)
        {
            Definicija definicija;

            using (Stream stream = File.Open(@"definicija.bin", FileMode.Open))
            {
                BinaryFormatter formater = new BinaryFormatter();
                definicija = (Definicija)formater.Deserialize(stream);
            }


            var listaUniformnihZnakova = new ListaUniformnihZnakova();

            var tablicaIzvornihZnakova = new TablicaIzvornihZnakova();

            #region "Dummy" podaci
            UniformniZnak prvi = new UniformniZnak()
            {
                BrojReda = 1,
                UniformniZnak_ = "c",
                IndeksUTabliciZnakova = 0
            };
            ZapisTabliceIzvornihZnakova prviZapis = new ZapisTabliceIzvornihZnakova()
            {
                Indeks = 0,
                IzvorniTekst = "da",
                UniformniZnak = "c"

            };
            UniformniZnak drugi = new UniformniZnak()
            {
                BrojReda = 2,
                UniformniZnak_ = "d",
                IndeksUTabliciZnakova = 1
            };
            ZapisTabliceIzvornihZnakova drugiZapis = new ZapisTabliceIzvornihZnakova()
            {
                Indeks = 1,
                IzvorniTekst = "ne",
                UniformniZnak = "d"
            };
            UniformniZnak treci = new UniformniZnak()
            {
                BrojReda = 3,
                UniformniZnak_ = "d",
                IndeksUTabliciZnakova = 1
            };

            listaUniformnihZnakova.DodajUniformniZnak(prvi);
            listaUniformnihZnakova.DodajUniformniZnak(drugi);
            listaUniformnihZnakova.DodajUniformniZnak(treci);
            tablicaIzvornihZnakova.DodajZnak(prviZapis);
            tablicaIzvornihZnakova.DodajZnak(drugiZapis);
            #endregion

            SintaksniAnalizator sintaksniAnalizator = new SintaksniAnalizator(listaUniformnihZnakova, tablicaIzvornihZnakova, definicija);
            sintaksniAnalizator.PokreniObradu();

            List<Produkcija> popisPrimijenjenihProdukcija = new List<Produkcija>();
            foreach (var redukcija in sintaksniAnalizator.PopisPrimijenjenihRedukcija)
            {
                popisPrimijenjenihProdukcija.Insert(0, redukcija);
            }

            Cvor korijenGenerativnogStabla = GradnjaGenerativnogStabla(popisPrimijenjenihProdukcija);
            Sucelje sucelje = new Sucelje (korijenGenerativnogStabla);
            sucelje.ShowDialog ();

        }

        

        public static Cvor GradnjaGenerativnogStabla(List<Produkcija> popisPrimijenjenihProdukcija)
        {
            List<Cvor> listaListova = new List<Cvor>();
            Cvor korijen = new Cvor(popisPrimijenjenihProdukcija[0].Glava);
            foreach (var znak in popisPrimijenjenihProdukcija[0].Tijelo.Split(' '))
            {
                Cvor noviCvor = new Cvor(znak);
                korijen.listaDjece.Add(noviCvor);
                listaListova.Add(noviCvor);
            }

            foreach (var produkcija in popisPrimijenjenihProdukcija)
            {
                if (popisPrimijenjenihProdukcija.IndexOf(produkcija) == 0)
                {
                    continue;
                }
                int indeksNajdesnijeg = -1;
                foreach (var cvor in listaListova)
                {
                    if (cvor.ime == produkcija.Glava)
                    {
                        indeksNajdesnijeg = listaListova.IndexOf(cvor);
                    }
                }

                foreach (var znak in produkcija.Tijelo.Split(' '))
                {
                    Cvor noviCvor = new Cvor(znak);
                    listaListova[indeksNajdesnijeg].listaDjece.Add(noviCvor);
                }

                listaListova.InsertRange(indeksNajdesnijeg + 1, listaListova[indeksNajdesnijeg].listaDjece);
                listaListova.RemoveAt(indeksNajdesnijeg);
            }

            return korijen;
        }

    }

    public class Cvor
    {
        public string ime { get; set; }
        public List<Cvor> listaDjece { get; set; }

        public Cvor(string ime)
        {
            this.ime = ime;
            listaDjece = new List<Cvor>();
        }
    }
}
